home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / cl_view.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-07  |  13.7 KB  |  612 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // cl_view.c -- player rendering positioning
  21.  
  22. #include "client.h"
  23.  
  24. //=============
  25. //
  26. // development tools for weapons
  27. //
  28. int            gun_frame;
  29. struct model_s    *gun_model;
  30.  
  31. //=============
  32.  
  33. cvar_t        *crosshair;
  34. cvar_t        *cl_testparticles;
  35. cvar_t        *cl_testentities;
  36. cvar_t        *cl_testlights;
  37. cvar_t        *cl_testblend;
  38.  
  39. cvar_t        *cl_stats;
  40.  
  41.  
  42. int            r_numdlights;
  43. dlight_t    r_dlights[MAX_DLIGHTS];
  44.  
  45. int            r_numstains;
  46. stain_t        r_stains[MAX_STAINS];
  47.  
  48. int            r_numentities;
  49. entity_t    r_entities[MAX_ENTITIES];
  50.  
  51. int            r_numparticles;
  52. particle_t    r_particles[MAX_PARTICLES];
  53.  
  54. lightstyle_t    r_lightstyles[MAX_LIGHTSTYLES];
  55.  
  56. char cl_weaponmodels[MAX_CLIENTWEAPONMODELS][MAX_QPATH];
  57. int num_cl_weaponmodels;
  58.  
  59. /*
  60. ====================
  61. V_ClearScene
  62.  
  63. Specifies the model that will be used as the world
  64. ====================
  65. */
  66. void V_ClearScene (void)
  67. {
  68.     r_numdlights = 0;
  69.     r_numstains = 0;
  70.     r_numentities = 0;
  71.     r_numparticles = 0;
  72. }
  73.  
  74.  
  75. /*
  76. =====================
  77. V_AddEntity
  78.  
  79. =====================
  80. */
  81. void V_AddEntity (entity_t *ent)
  82. {
  83.     if (r_numentities >= MAX_ENTITIES)
  84.         return;
  85.     r_entities[r_numentities++] = *ent;
  86. }
  87.  
  88.  
  89. /*
  90. =====================
  91. V_AddParticle
  92.  
  93. =====================
  94. */
  95. void V_AddParticle (vec3_t org, int color, int type, float alpha)
  96. {
  97.     particle_t    *p;
  98.  
  99.     if (r_numparticles >= MAX_PARTICLES)
  100.         return;
  101.     p = &r_particles[r_numparticles++];
  102.     VectorCopy (org, p->origin);
  103.     p->color = color;
  104.     p->alpha = alpha;
  105.     p->type = type;
  106. }
  107.  
  108. /*
  109. =====================
  110. V_AddLight
  111.  
  112. =====================
  113. */
  114. void V_AddLight (vec3_t org, float intensity, float r, float g, float b)
  115. {
  116.     dlight_t    *dl;
  117.  
  118.     if (r_numdlights >= MAX_DLIGHTS)
  119.         return;
  120.     dl = &r_dlights[r_numdlights++];
  121.     VectorCopy (org, dl->origin);
  122.     dl->intensity = intensity;
  123.     dl->color[0] = r;
  124.     dl->color[1] = g;
  125.     dl->color[2] = b;
  126. }
  127.  
  128. /*
  129. =====================
  130. V_AddStain
  131.  
  132. =====================
  133. */
  134. void V_AddStain (vec3_t org, float intensity, float r, float g, float b, float a)
  135. {
  136.     stain_t        *st;
  137.  
  138.     if (r_numstains >= MAX_STAINS)
  139.         return;
  140.     st = &r_stains[r_numstains++];
  141.     VectorCopy (org, st->origin);
  142.     st->intensity = intensity;
  143.     st->color[0] = r;
  144.     st->color[1] = g;
  145.     st->color[2] = b;
  146.     st->alpha = a;
  147. }
  148.  
  149. /*
  150. =====================
  151. V_AddLightStyle
  152.  
  153. =====================
  154. */
  155. void V_AddLightStyle (int style, float r, float g, float b)
  156. {
  157.     lightstyle_t    *ls;
  158.  
  159.     if (style < 0 || style > MAX_LIGHTSTYLES)
  160.         Com_Error (ERR_DROP, "Bad light style %i", style);
  161.     ls = &r_lightstyles[style];
  162.  
  163.     ls->white = r+g+b;
  164.     ls->rgb[0] = r;
  165.     ls->rgb[1] = g;
  166.     ls->rgb[2] = b;
  167. }
  168.  
  169. /*
  170. ================
  171. V_TestParticles
  172.  
  173. If cl_testparticles is set, create 4096 particles in the view
  174. ================
  175. */
  176. void V_TestParticles (void)
  177. {
  178.     particle_t    *p;
  179.     int            i, j;
  180.     float        d, r, u;
  181.  
  182.     r_numparticles = MAX_PARTICLES;
  183.     for (i=0 ; i<r_numparticles ; i++)
  184.     {
  185.         d = i*0.25;
  186.         r = 4*((i&7)-3.5);
  187.         u = 4*(((i>>3)&7)-3.5);
  188.         p = &r_particles[i];
  189.  
  190.         for (j=0 ; j<3 ; j++)
  191.             p->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*d +
  192.             cl.v_right[j]*r + cl.v_up[j]*u;
  193.  
  194.         p->color = 8;
  195.         p->alpha = cl_testparticles->value;
  196.     }
  197. }
  198.  
  199. /*
  200. ================
  201. V_TestEntities
  202.  
  203. If cl_testentities is set, create 32 player models
  204. ================
  205. */
  206. void V_TestEntities (void)
  207. {
  208.     int            i, j;
  209.     float        f, r;
  210.     entity_t    *ent;
  211.  
  212.     r_numentities = 32;
  213.     memset (r_entities, 0, sizeof(r_entities));
  214.  
  215.     for (i=0 ; i<r_numentities ; i++)
  216.     {
  217.         ent = &r_entities[i];
  218.  
  219.         r = 64 * ( (i%4) - 1.5 );
  220.         f = 64 * (i/4) + 128;
  221.  
  222.         for (j=0 ; j<3 ; j++)
  223.             ent->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*f +
  224.             cl.v_right[j]*r;
  225.  
  226.         ent->model = cl.baseclientinfo.model;
  227.         ent->skin = cl.baseclientinfo.skin;
  228.     }
  229. }
  230.  
  231. /*
  232. ================
  233. V_TestLights
  234.  
  235. If cl_testlights is set, create 32 lights models
  236. ================
  237. */
  238. void V_TestLights (void)
  239. {
  240.     int            i, j;
  241.     float        f, r;
  242.     dlight_t    *dl;
  243.  
  244.     r_numdlights = 32;
  245.     memset (r_dlights, 0, sizeof(r_dlights));
  246.  
  247.     for (i=0 ; i<r_numdlights ; i++)
  248.     {
  249.         dl = &r_dlights[i];
  250.  
  251.         r = 64 * ( (i%4) - 1.5 );
  252.         f = 64 * (i/4) + 128;
  253.  
  254.         for (j=0 ; j<3 ; j++)
  255.             dl->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*f +
  256.             cl.v_right[j]*r;
  257.         dl->color[0] = ((i%6)+1) & 1;
  258.         dl->color[1] = (((i%6)+1) & 2)>>1;
  259.         dl->color[2] = (((i%6)+1) & 4)>>2;
  260.         dl->intensity = 200;
  261.     }
  262. }
  263.  
  264. //===================================================================
  265.  
  266. /*
  267. =================
  268. CL_PrepRefresh
  269.  
  270. Call before entering a new level, or after changing dlls
  271. =================
  272. */
  273. void CL_PrepRefresh (void)
  274. {
  275.     char        mapname[32];
  276.     int            i;
  277.     char        name[MAX_QPATH];
  278.     float        rotate;
  279.     vec3_t        axis;
  280.  
  281.     if (!cl.configstrings[CS_MODELS+1][0])
  282.         return;        // no map loaded
  283.  
  284.     SCR_AddDirtyPoint (0, 0);
  285.     SCR_AddDirtyPoint (viddef.width-1, viddef.height-1);
  286.  
  287.     // let the render dll load the map
  288.     strcpy (mapname, cl.configstrings[CS_MODELS+1] + 5);    // skip "maps/"
  289.     mapname[strlen(mapname)-4] = 0;        // cut off ".bsp"
  290.  
  291.     // register models, pics, and skins
  292.     Com_Printf ("Map: %s\r", mapname); 
  293.     SCR_UpdateScreen ();
  294.     R_BeginRegistration (mapname);
  295.     Com_Printf ("                                     \r");
  296.  
  297.     // precache status bar pics
  298.     Com_Printf ("pics\r"); 
  299.     SCR_UpdateScreen ();
  300.     SCR_TouchPics ();
  301.     Com_Printf ("                                     \r");
  302.  
  303.     CL_RegisterTEntModels ();
  304.  
  305.     num_cl_weaponmodels = 1;
  306.     strcpy(cl_weaponmodels[0], "weapon.md2");
  307.  
  308.     for (i=1 ; i<MAX_MODELS && cl.configstrings[CS_MODELS+i][0] ; i++)
  309.     {
  310.         strcpy (name, cl.configstrings[CS_MODELS+i]);
  311.         name[37] = 0;    // never go beyond one line
  312.         if (name[0] != '*')
  313.             Com_Printf ("%s\r", name); 
  314.         SCR_UpdateScreen ();
  315.         Sys_SendKeyEvents ();    // pump message loop
  316.         if (name[0] == '#')
  317.         {
  318.             // special player weapon model
  319.             if (num_cl_weaponmodels < MAX_CLIENTWEAPONMODELS)
  320.             {
  321.                 strncpy(cl_weaponmodels[num_cl_weaponmodels], cl.configstrings[CS_MODELS+i]+1,
  322.                     sizeof(cl_weaponmodels[num_cl_weaponmodels]) - 1);
  323.                 num_cl_weaponmodels++;
  324.             }
  325.         } 
  326.         else
  327.         {
  328.             cl.model_draw[i] = R_RegisterModel (cl.configstrings[CS_MODELS+i]);
  329.             if (name[0] == '*')
  330.                 cl.model_clip[i] = CM_InlineModel (cl.configstrings[CS_MODELS+i]);
  331.             else
  332.                 cl.model_clip[i] = NULL;
  333.         }
  334.         if (name[0] != '*')
  335.             Com_Printf ("                                     \r");
  336.     }
  337.  
  338.     Com_Printf ("images\r", i); 
  339.     SCR_UpdateScreen ();
  340.     for (i=1 ; i<MAX_IMAGES && cl.configstrings[CS_IMAGES+i][0] ; i++)
  341.     {
  342.         cl.image_precache[i] = R_RegisterPic (cl.configstrings[CS_IMAGES+i]);
  343.         Sys_SendKeyEvents ();    // pump message loop
  344.     }
  345.     
  346.     Com_Printf ("                                     \r");
  347.     for (i=0 ; i<MAX_CLIENTS ; i++)
  348.     {
  349.         if (!cl.configstrings[CS_PLAYERSKINS+i][0])
  350.             continue;
  351.         Com_Printf ("client %i\r", i); 
  352.         SCR_UpdateScreen ();
  353.         Sys_SendKeyEvents ();    // pump message loop
  354.         CL_ParseClientinfo (i);
  355.         Com_Printf ("                                     \r");
  356.     }
  357.  
  358.     CL_LoadClientinfo (&cl.baseclientinfo, "unnamed\\male/grunt");
  359.  
  360.     // set sky textures and speed
  361.     Com_Printf ("sky\r", i); 
  362.     SCR_UpdateScreen ();
  363.     rotate = atof (cl.configstrings[CS_SKYROTATE]);
  364.     sscanf (cl.configstrings[CS_SKYAXIS], "%f %f %f", 
  365.         &axis[0], &axis[1], &axis[2]);
  366.     R_SetSky (cl.configstrings[CS_SKY], rotate, axis);
  367.     Com_Printf ("                                     \r");
  368.  
  369.     // the renderer can now free unneeded stuff
  370.     R_EndRegistration ();
  371.  
  372.     // clear any lines of console text
  373.     Con_ClearNotify ();
  374.  
  375.     SCR_UpdateScreen ();
  376.     cl.refresh_prepped = true;
  377.     cl.force_refdef = true;    // make sure we have a valid refdef
  378.  
  379.     // start the cd track
  380.     CDAudio_Play (atoi(cl.configstrings[CS_CDTRACK]), true);
  381. }
  382.  
  383. /*
  384. ====================
  385. CalcFov
  386. ====================
  387. */
  388. float CalcFov (float fov_x, float width, float height)
  389. {
  390.     float    a;
  391.     float    x;
  392.  
  393.     if (fov_x < 1 || fov_x > 179)
  394.         Com_Error (ERR_DROP, "Bad fov: %f", fov_x);
  395.  
  396.     x = width/tan(fov_x/360*M_PI);
  397.  
  398.     a = atan (height/x);
  399.  
  400.     a = a*360/M_PI;
  401.  
  402.     return a;
  403. }
  404.  
  405. //============================================================================
  406.  
  407. // gun frame debugging functions
  408. void V_Gun_Next_f (void)
  409. {
  410.     gun_frame++;
  411.     Com_Printf ("frame %i\n", gun_frame);
  412. }
  413.  
  414. void V_Gun_Prev_f (void)
  415. {
  416.     gun_frame--;
  417.     if (gun_frame < 0)
  418.         gun_frame = 0;
  419.     Com_Printf ("frame %i\n", gun_frame);
  420. }
  421.  
  422. void V_Gun_Model_f (void)
  423. {
  424.     char    name[MAX_QPATH];
  425.  
  426.     if (Cmd_Argc() != 2)
  427.     {
  428.         gun_model = NULL;
  429.         return;
  430.     }
  431.     Com_sprintf (name, sizeof(name), "models/%s/tris.md2", Cmd_Argv(1));
  432.     gun_model = R_RegisterModel (name);
  433. }
  434.  
  435. //============================================================================
  436.  
  437.  
  438. /*
  439. =================
  440. SCR_DrawCrosshair
  441. =================
  442. */
  443. void SCR_DrawCrosshair (void)
  444. {
  445.     if (!crosshair->value)
  446.         return;
  447.  
  448.     if (crosshair->modified)
  449.     {
  450.         crosshair->modified = false;
  451.         SCR_TouchPics ();
  452.     }
  453.  
  454.     if (!crosshair_pic[0])
  455.         return;
  456.  
  457.     Draw_Pic (scr_vrect.x + ((scr_vrect.width - crosshair_width)>>1)
  458.     , scr_vrect.y + ((scr_vrect.height - crosshair_height)>>1), crosshair_pic);
  459. }
  460.  
  461. /*
  462. ==================
  463. V_RenderView
  464.  
  465. ==================
  466. */
  467. void V_RenderView( float stereo_separation )
  468. {
  469.     extern int entitycmpfnc( const entity_t *, const entity_t * );
  470.  
  471.     if (cls.state != ca_active)
  472.         return;
  473.  
  474.     if (!cl.refresh_prepped)
  475.         return;            // still loading
  476.  
  477.     if (cl_timedemo->value)
  478.     {
  479.         if (!cl.timedemo_start)
  480.             cl.timedemo_start = Sys_Milliseconds ();
  481.         cl.timedemo_frames++;
  482.     }
  483.  
  484.     // an invalid frame will just use the exact previous refdef
  485.     // we can't use the old frame if the video mode has changed, though...
  486.     if ( cl.frame.valid && (cl.force_refdef || !cl_paused->value) )
  487.     {
  488.         cl.force_refdef = false;
  489.  
  490.         // build a refresh entity list and calc cl.sim*
  491.         // this also calls CL_CalcViewValues which loads
  492.         // v_forward, etc.
  493.         CL_AddEntities ();
  494.  
  495.         if (cl_testparticles->value)
  496.             V_TestParticles ();
  497.         if (cl_testentities->value)
  498.             V_TestEntities ();
  499.         if (cl_testlights->value)
  500.             V_TestLights ();
  501.         if (cl_testblend->value)
  502.         {
  503.             cl.refdef.blend[0] = 1;
  504.             cl.refdef.blend[1] = 0.5;
  505.             cl.refdef.blend[2] = 0.25;
  506.             cl.refdef.blend[3] = 0.5;
  507.         }
  508.  
  509.         // offset vieworg appropriately if we're doing stereo separation
  510.         if ( stereo_separation != 0 )
  511.         {
  512.             vec3_t tmp;
  513.  
  514.             VectorScale( cl.v_right, stereo_separation, tmp );
  515.             VectorAdd( cl.refdef.vieworg, tmp, cl.refdef.vieworg );
  516.         }
  517.  
  518.         // never let it sit exactly on a node line, because a water plane can
  519.         // dissapear when viewed with the eye exactly on it.
  520.         // the server protocol only specifies to 1/8 pixel, so add 1/16 in each axis
  521.         cl.refdef.vieworg[0] += 1.0/16;
  522.         cl.refdef.vieworg[1] += 1.0/16;
  523.         cl.refdef.vieworg[2] += 1.0/16;
  524.  
  525.         cl.refdef.x = scr_vrect.x;
  526.         cl.refdef.y = scr_vrect.y;
  527.         cl.refdef.width = scr_vrect.width;
  528.         cl.refdef.height = scr_vrect.height;
  529.         cl.refdef.fov_y = CalcFov (cl.refdef.fov_x, cl.refdef.width, cl.refdef.height);
  530.         cl.refdef.time = cl.time*0.001;
  531.  
  532.         cl.refdef.areabits = cl.frame.areabits;
  533.  
  534.         if (!cl_add_entities->value)
  535.             r_numentities = 0;
  536.         if (!cl_add_particles->value)
  537.             r_numparticles = 0;
  538.         if (!cl_add_lights->value)
  539.             r_numdlights = 0;
  540.         if (!cl_add_blend->value)
  541.         {
  542.             VectorClear (cl.refdef.blend);
  543.         }
  544.  
  545.         cl.refdef.num_entities = r_numentities;
  546.         cl.refdef.entities = r_entities;
  547.         cl.refdef.num_particles = r_numparticles;
  548.         cl.refdef.particles = r_particles;
  549.         cl.refdef.num_dlights = r_numdlights;
  550.         cl.refdef.dlights = r_dlights;
  551.         cl.refdef.num_stains = r_numstains;
  552.         cl.refdef.stains = r_stains;
  553.         cl.refdef.lightstyles = r_lightstyles;
  554.  
  555.         cl.refdef.rdflags = cl.frame.playerstate.rdflags;
  556.  
  557.         // sort entities for better cache locality
  558.         qsort( cl.refdef.entities, cl.refdef.num_entities, sizeof( cl.refdef.entities[0] ), (int (*)(const void *, const void *))entitycmpfnc );
  559.  
  560.         V_ClearScene ();
  561.     }
  562.  
  563.     R_RenderFrame (&cl.refdef);
  564.     if (cl_stats->value)
  565.         Com_Printf ("ent:%i  lt:%i  part:%i\n", r_numentities, r_numdlights, r_numparticles);
  566.     if ( log_stats->value && ( log_stats_file != 0 ) )
  567.         fprintf( log_stats_file, "%i,%i,%i,",r_numentities, r_numdlights, r_numparticles);
  568.  
  569.  
  570.     SCR_AddDirtyPoint (scr_vrect.x, scr_vrect.y);
  571.     SCR_AddDirtyPoint (scr_vrect.x+scr_vrect.width-1,
  572.         scr_vrect.y+scr_vrect.height-1);
  573.  
  574.     SCR_DrawCrosshair ();
  575. }
  576.  
  577.  
  578. /*
  579. =============
  580. V_Viewpos_f
  581. =============
  582. */
  583. void V_Viewpos_f (void)
  584. {
  585.     Com_Printf ("(%i %i %i) : %i\n", (int)cl.refdef.vieworg[0],
  586.         (int)cl.refdef.vieworg[1], (int)cl.refdef.vieworg[2], 
  587.         (int)cl.refdef.viewangles[YAW]);
  588. }
  589.  
  590. /*
  591. =============
  592. V_Init
  593. =============
  594. */
  595. void V_Init (void)
  596. {
  597.     Cmd_AddCommand ("gun_next", V_Gun_Next_f);
  598.     Cmd_AddCommand ("gun_prev", V_Gun_Prev_f);
  599.     Cmd_AddCommand ("gun_model", V_Gun_Model_f);
  600.  
  601.     Cmd_AddCommand ("viewpos", V_Viewpos_f);
  602.  
  603.     crosshair = Cvar_Get ("crosshair", "0", CVAR_ARCHIVE);
  604.  
  605.     cl_testblend = Cvar_Get ("cl_testblend", "0", 0);
  606.     cl_testparticles = Cvar_Get ("cl_testparticles", "0", 0);
  607.     cl_testentities = Cvar_Get ("cl_testentities", "0", 0);
  608.     cl_testlights = Cvar_Get ("cl_testlights", "0", 0);
  609.  
  610.     cl_stats = Cvar_Get ("cl_stats", "0", 0);
  611. }
  612.